﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BT_DoHoa_Nhom13.DiagramFactorys;
using BT_DoHoa_Nhom13.EffectLib;
using System.Windows.Forms;
using BT_DoHoa_Nhom13.Lib;
using System.Drawing;
using BT_DoHoa_Nhom13.ShapeLib;
using BT_DoHoa_Nhom13.GraphicLib;
using System.IO;


namespace BT_DoHoa_Nhom13
{
    public class MyPanel
    {
        MyShape currentShape;
        MyGraphic currentGraphic;

        MyDiagramFactory currentFactory;
        List<MyShape> drawedShapes;
        List<MyShape> lstNormalShapes;
        List<MyDiagramFactory> lstFactory;
        List<MyGraphic> lstFileGraphic;
        List<MyEffect> availableEffect;
        List<MyEffect> currentEffect;
        List<MyGraphic> lstGraphic;

        public MyPanel(Panel panel)
        { 
            currentEffect = new List<MyEffect>();
            drawedShapes = new List<MyShape>();
            CreateListFactory();
            CreateListEffect();
            CreateListGraphic();
            CreateListNormalShape();
            CreateListFileGraphic(panel.Width, panel.Height);
        }

        private void CreateListFactory()
        {
            lstFactory = new List<MyDiagramFactory>();
            lstFactory.Add(ActivityFactory.GetInstance());
            lstFactory.Add(FlowChartFactory.GetInstance());
            lstFactory.Add(DFDFactory.GetInstance());
        }

        private void CreateListEffect()
        {
            availableEffect = new List<MyEffect>();
            availableEffect.Add(BorderEffect.GetInstance());
            availableEffect.Add(HightLightEffect.GetInstance());
            availableEffect.Add(ShadowEffect.GetInstance());
        }

        private void CreateListGraphic()
        {
            lstGraphic = new List<MyGraphic>();
            lstGraphic.Add(CairoGraphic.GetInstance());
            lstGraphic.Add(GDIPlusGraphic.GetInstance());
        }

        private void CreateListFileGraphic(int panelWidth, int panelHeight)
        {
            lstFileGraphic = new List<MyGraphic>();
            lstFileGraphic.Add(PNGCairoGraphic.GetInstance("",panelWidth,panelHeight));
            lstFileGraphic.Add(PNGGDIPlusGraphic.GetInstance("", panelWidth, panelHeight));
        }

        private void CreateListNormalShape()
        {
            lstNormalShapes = new List<MyShape>();
            lstNormalShapes.Add(new MyLine());
            lstNormalShapes.Add(new MyRectangle());
            lstNormalShapes.Add(new MyEllipse());
        }

        public List<String> GetAvailableShapes()
        {
            if(currentFactory == null)
            {
                return GetListNormalShape();
            }
            else
            {
                return GetListDiagramShape();
            }
        }

        private List<String> GetListNormalShape()
        {
            List<String> lstShapes = lstNormalShapes.Select(item => item.GetName()).ToList();
            return lstShapes;
        }

        private List<String> GetListDiagramShape()
        {
            MyDiagramFactory defaultFactory = lstFactory.FirstOrDefault();
            List<String> lstShapes = new List<string>();
            if(defaultFactory != null)
            {
                lstShapes = defaultFactory.GetListNameShape();
            }

            return lstShapes;
        }

        public void SetCurrentGraphic(String name, Panel panel)
        {
            foreach(MyGraphic g in lstGraphic)
            {
                if(g.GetName() == name)
                {
                    currentGraphic = g;
                    break;
                }
            }
        }

        public List<String> GetNameOfGraphics()
        {
            return lstGraphic.Select(item => item.GetName()).ToList();
        }

        public List<String> GetListNameOfFactory()
        {
            List<String> result = lstFactory.Select(item => item.GetName()).ToList();
            return result;
        }

        public void SetCurrentFactory(String name)
        {
            MyDiagramFactory oldFactory = currentFactory;
            currentFactory = null;
            foreach(MyDiagramFactory factory in lstFactory)
            {
                if(factory.GetName() == name)
                {
                    currentFactory = factory;
                    break;
                }
            }

            if (currentFactory == null || oldFactory == null)
            {
                drawedShapes.Clear();
            }
            else
            {
                //Convert diagram
                List<MyShape> newShapes = new List<MyShape>();
                foreach(MyShape shape in drawedShapes)
                {
                    MyShape temp = shape.CloneByDiagramFactory(currentFactory);
                    if(temp!=null)
                    {
                        newShapes.Add(temp);
                    }
                }

                drawedShapes = newShapes;
            }

        }

        public void AddEffect(String name)
        {
            MyEffect newEffect = availableEffect.Where(item => item.GetName() == name).FirstOrDefault(); 
            if(!currentEffect.Contains(newEffect))
            {
                currentEffect.Add(newEffect);
            }
        }

        public void RemoveEffect(String name)
        {
            MyEffect removedEffect = availableEffect.Where(item => item.GetName() == name).FirstOrDefault(); 
            if(currentEffect.Contains(removedEffect))
            {
                currentEffect.Remove(removedEffect);
            }
        }

        public void SetCurrentShape(String name)
        {
            currentShape = null;
            if (currentFactory == null)
            {
                foreach (MyShape shape in lstNormalShapes)
                {
                    if(shape.GetName() == name)
                    {
                        currentShape = shape.Clone();
                        break;
                    }
                }
            }
            else
            {
                currentShape = GetShapeFromDiagram(name);
            }
        }

        private MyShape GetShapeFromDiagram(String name)
        {
            switch(name)
            {
                case "Start":
                    return currentFactory.GetStartShape();

                case "End":
                    return currentFactory.GetEndShape();

                case "Process":
                    return currentFactory.GetProcessShape();

                case "Condition":
                    return currentFactory.GetConditionShape();

                case "Input":
                    return currentFactory.GetInputShape();

                case "Output":
                    return currentFactory.GetOutputShape();

                case "Arrow":
                    return currentFactory.GetArrowShape();
            }

            return null;
        }

        public void MouseDown(int x, int y)
        {
            drawedShapes.Add(currentShape);
            currentShape.SetStartPoint(x, y);
        }

        public void MouseUp(int x, int y)
        {
            currentShape.SetEndPoint(x, y);
            currentShape = currentShape.Clone();
        }

        public void MouseMove(int x, int y)
        {
            currentShape.SetEndPoint(x, y);
        }

        public void Draw(Graphics g)
        {
            currentGraphic.SetGraphicInfo(g, "");
            foreach (MyShape shape in drawedShapes)
            {
                shape.Draw(currentGraphic, currentEffect);
            }
        }

        public void Clear()
        {
            drawedShapes.Clear();
        }

        public void Save(String path, int panelWidth, int panelHeight)
        {
            String format = Path.GetExtension(path);
            MyGraphic saveGraphic = null;
            foreach(MyGraphic graphic in lstFileGraphic)
            {
                if (graphic.GetName().ToLower().Contains(format.ToLower()) 
                    && graphic.GetName().ToLower().Contains(currentGraphic.GetName().ToLower()))
                {
                    saveGraphic = graphic;
                    break;
                }
            }
            

            if(saveGraphic!=null)
            {
                saveGraphic.SetGraphicInfo(null, path);
                foreach(MyShape shape in drawedShapes)
                {
                    shape.Draw(saveGraphic, currentEffect);
                }
            }
        }
    }
}
